﻿using System.Security.Permissions;
using System.Windows.Forms;
using System;
using Microsoft.VisualStudio.TextManager.Interop;
using Microsoft.VisualStudio.OLE.Interop;
using Microsoft.VisualStudio.Shell.Interop;
using SKYPE4COMLib;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace Mycos.SkypeVs
{
    /// <summary>
    /// Summary description for MyControl.
    /// </summary>
    public partial class SkypeStudioControl : UserControl,  IVsRunningDocTableEvents, IOleCommandTarget
    {
        #region Field
        protected uint _rdtEventCookie;
        protected EventHandler _textEventHandler = null;
        protected SkypeStudioToolWindow m_Parent;
        private Skype skype;
        private string m_CurrentUserId = "Hello world";
        string m_FileName = string.Empty;
        string m_SelectText = string.Empty;
        protected IVsTextView _textView = null;
        protected IOleCommandTarget _nextCommandTarget;

        #endregion

        #region Property
        IVsRunningDocumentTable RDT
        {
            get
            {
                IVsRunningDocumentTable rdt = (IVsRunningDocumentTable)GetService(
                    typeof(SVsRunningDocumentTable));
                if (rdt == null)
                    throw new Exception("Couldn't obtain RDT");
                return rdt;
            }
        }
        public string CurrentUserId
        {
            get
            {
                return m_CurrentUserId;
            }
            set
            {
                m_CurrentUserId = value;
            }
        }
        #endregion

        #region Constructor
        public SkypeStudioControl(SkypeStudioToolWindow windowPane)
        {
            m_Parent = windowPane;
            InitializeComponent();

            skype = new SkypeClass();
            if (!skype.Client.IsRunning)
            {
                skype.Client.Start(true, true);
                System.Threading.Thread.Sleep(300);
            }

            this.skype.Attach(8, false);
            this.skype.MessageStatus += this.SkypeMessageStatusChanged;
            //this.skype.ApplicationReceiving += new _ISkypeEvents_ApplicationReceivingEventHandler(skype_ApplicationReceiving);
            //this.skype.ContactsFocused += new _ISkypeEvents_ContactsFocusedEventHandler(skype_ContactsFocused);
            //this.skype.UserStatus += new _ISkypeEvents_UserStatusEventHandler(skype_UserStatus);

            //axSkypeContactList1.SelectionChange += new AxSKYPECONTACTSLib._DSkypeContactListEvents_SelectionChangeEventHandler(axSkypeContactList1_SelectionChange);
            RDT.AdviseRunningDocTableEvents(this, out _rdtEventCookie);

            IVsTextView textView = null;
            IVsTextManager textManager = GetService(typeof(SVsTextManager)) as IVsTextManager;
            textManager.GetActiveView(1, null, out textView);
            HandleTextViewChange(textView);
        }

   
        public SkypeStudioControl()
        {
            InitializeComponent();
        }
        #endregion

        #region Method : Private
        private void HandleTextViewChange(IVsTextView textView)
        {
            if (_textView != null)
            {
                _textView.RemoveCommandFilter(this);
            }

            _textView = textView;

            if (_textView != null)
            {
                _textView.AddCommandFilter(this, out _nextCommandTarget);
            }
        }
        private void WriteToOutput(string str)
        {
            IVsOutputWindow outWindow = this.GetService(typeof(SVsOutputWindow)) as IVsOutputWindow;

            Guid normalOutWindowGuid = Microsoft.VisualStudio.VSConstants.GUID_OutWindowGeneralPane;
            IVsOutputWindowPane outputWidowPane;
            outWindow.GetPane(ref normalOutWindowGuid, out outputWidowPane);

            outputWidowPane.OutputString(str);
        }

        public void SendMessage()
        {
            //MessageBox.Show(this.m_FileName);
            //MessageBox.Show(this.m_SelectText);
            if (axSkypeContactList1.Selection != null && axSkypeContactList1.Selection.Count > 0)
            {
                foreach (User var in axSkypeContactList1.Selection)
                {
                    skype.SendMessage(var.Handle, this.m_SelectText);
                }
            }
        }
        #endregion

        #region Method : Overide Cotrol
        protected override object GetService(Type service)
        {

            object obj = null;
            if (m_Parent != null)
            {
                obj = m_Parent.GetVsService(service);
            }
            if (obj == null)
            {
                obj = base.GetService(service);
            }
            return obj;
        }
        #endregion

        #region EventHandler : Skype
        void skype_UserStatus(TUserStatus Status)
        {
            WriteToOutput("skype_UserStatus");
        }

        void skype_ContactsFocused(string Username)
        {
            WriteToOutput("skype_ContactsFocused");
        }

        void skype_ApplicationReceiving(SKYPE4COMLib.Application pApp, ApplicationStreamCollection pStreams)
        {
            WriteToOutput("skype_ApplicationReceiving");
        }

        private void axSkypeContactList1_OnlineStatusChange(object sender, AxSKYPECONTACTSLib._DSkypeContactListEvents_OnlineStatusChangeEvent e)
        {
            MessageBox.Show(e.user.Aliases + " " + e.status.ToString());
        }
        void SkypeMessageStatusChanged(ChatMessage message, TChatMessageStatus status)
        {
            if (status == TChatMessageStatus.cmsReceived)
            {
                //string msg = string.Format("{0} : {1}\n", message.Sender.FullName, message.Body);
                //WriteToOutput(msg);
                //this.htmlRichTextBox1.Items.Add(new ReceiveMessage(message));
                //listReceive.SelectedIndex = listReceive.Items.Count - 1;

                this.htmlRichTextBox1.AddHTML(string.Format("<b>{0} : </b>\n{1}\n\n", string.IsNullOrEmpty(message.Sender.FullName) ? message.Sender.Handle : message.Sender.FullName, message.Body));
                Debug.WriteLine(string.Format("Add ChatMessage {0}, TChatMessageStatus {1}", message.Body, status.ToString()));
            }
        }

        #endregion

        #region Default

        /// <summary> 
        /// Let this control process the mnemonics.
        /// </summary>
        [UIPermission(SecurityAction.LinkDemand, Window = UIPermissionWindow.AllWindows)]
        protected override bool ProcessDialogChar(char charCode)
        {
            // If we're the top-level form or control, we need to do the mnemonic handling
            if (charCode != ' ' && ProcessMnemonic(charCode))
            {
                return true;
            }
            return base.ProcessDialogChar(charCode);
        }

        /// <summary>
        /// Enable the IME status handling for this control.
        /// </summary>
        protected override bool CanEnableIme
        {
            get
            {
                return true;
            }
        }

        #endregion

        #region EventHandler
        private void btnSendSelectTest_Click(object sender, EventArgs e)
        {
            SendMessage();
        }

        private void axSkypeContactList1_SelectionChange(object sender, AxSKYPECONTACTSLib._DSkypeContactListEvents_SelectionChangeEvent e)
        {
            this.btnSendSelectTest.Enabled = !string.IsNullOrEmpty(this.m_SelectText) && axSkypeContactList1.Selection.Count > 0;
        }

        private void btnSend_Click(object sender, EventArgs e)
        {
            if (axSkypeContactList1.Selection != null && axSkypeContactList1.Selection.Count > 0)
            {
                foreach (User var in axSkypeContactList1.Selection)
                {
                    skype.SendMessage(var.Handle, this.txtSendText.Text);
                }
            }
            this.txtSendText.Text = string.Empty;
        }

        private void txtSendText_TextChanged(object sender, EventArgs e)
        {
            this.btnSend.Enabled = !string.IsNullOrEmpty(this.txtSendText.Text);
        }

        private void txtSendText_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyData == Keys.Enter)
                btnSend_Click(null, EventArgs.Empty);
        }
     
        #endregion
      
        #region IVsRunningDocTableEvents Members

        int IVsRunningDocTableEvents.OnAfterAttributeChange(uint docCookie, uint grfAttribs)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        int IVsRunningDocTableEvents.OnAfterDocumentWindowHide(uint docCookie, IVsWindowFrame pFrame)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        int IVsRunningDocTableEvents.OnAfterFirstDocumentLock(uint docCookie, uint dwRDTLockType, uint dwReadLocksRemaining, uint dwEditLocksRemaining)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        int IVsRunningDocTableEvents.OnAfterSave(uint docCookie)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        int IVsRunningDocTableEvents.OnBeforeDocumentWindowShow(uint docCookie, int fFirstShow, IVsWindowFrame pFrame)
        {

            IntPtr pCodeWindow;
            Guid riid = typeof(IVsCodeWindow).GUID;


            pFrame.QueryViewInterface(ref riid, out pCodeWindow);
            if (pCodeWindow.ToInt32() == 0)
            {
                HandleTextViewChange(null);
                return 0;
            }

            IVsCodeWindow codeWindow = (IVsCodeWindow)Marshal.GetObjectForIUnknown(pCodeWindow);

            IVsTextView textView = null;
            codeWindow.GetPrimaryView(out textView);

            HandleTextViewChange(textView);

            uint flags;
            uint readLocks;
            uint writeLoks;
            string filePath;
            IVsHierarchy hierarchy;
            uint itemId;
            IntPtr unkDocData;
            int hr = RDT.GetDocumentInfo(docCookie, out flags, out readLocks, out writeLoks,
                out filePath, out hierarchy, out itemId, out unkDocData);
            m_FileName = filePath;

            return 0;
        }

        int IVsRunningDocTableEvents.OnBeforeLastDocumentUnlock(uint docCookie, uint dwRDTLockType, uint dwReadLocksRemaining, uint dwEditLocksRemaining)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        #endregion

        #region IOleCommandTarget Members

        int IOleCommandTarget.Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
        {
            Microsoft.VisualStudio.VSConstants.VSStd2KCmdID command = (Microsoft.VisualStudio.VSConstants.VSStd2KCmdID)nCmdID;
            string selectedText = "";
            _textView.GetSelectedText(out selectedText);
            this.m_SelectText = selectedText;
            this.btnSendSelectTest.Enabled = !string.IsNullOrEmpty(this.m_SelectText) && axSkypeContactList1.Selection.Count > 0;
            //switch (command)
            //{
            //    case Microsoft.VisualStudio.VSConstants.VSStd2KCmdID.MAKEABSOLUTE:
            //        this.textBox1.TextChanged -= _textEventHandler;
            //        this.textBox1.Text = selectedText;
            //        this.textBox1.TextChanged += _textEventHandler;
            //        break;
            //}


            //Microsoft.VisualStudio.VSConstants.VSStd2KCmdID.SELECT_TAG
            System.Diagnostics.Debug.WriteLine(string.Format("Exec: CommandGroup: {0}, CommandId: {1}", pguidCmdGroup, command));
            return _nextCommandTarget.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
        }

        int IOleCommandTarget.QueryStatus(ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText)
        {
            return _nextCommandTarget.QueryStatus(ref pguidCmdGroup, cCmds, prgCmds, pCmdText);
        }

        #endregion
}
}
